﻿using ICPFrameLib.Business;
using ICPFrameLib.Attributes;
using XHRPMIS.Common;
using EFFC.Frame.Net.Base.Common;
using EFFC.Frame.Net.Base.Data.Base;
using EFFC.Frame.Net.Module.Extend.EWRA.Attributes;
using EFFC.Frame.Net.Module.Extend.EWRA.Attributes.Validation;
using EFFC.Frame.Net.Unit.DB.Parameters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EFFC.Extends.LinqDLR2SQL;
using EFFC.Frame.Net.Unit.DB;
using EFFC.Frame.Net.Base.Data;
using System.IO;
using EFFC.Frame.Net.Base.Constants;
using System.Text.RegularExpressions;
using System.Text;
using ICPFrameLib.Common;

namespace XHRPMIS.Business.v1._0
{
    public class Events4DForm : MyRestLogic
    {
        [EWRARouteDesc("获取所有的自定义事件资料")]
        [EWRAOutputDesc("返回结果", @"{
    code:'success-成功，failed-失败',
    msg:'提示信息',
    data:[{
        no:'事件编号',
        name:'事件名称',
        category:'事件分类，如下：MetaData-元数据事件，Customerize-自定义',
        desc:'事件描述',
        request_parameters:'事件参数设定，采用json格式，格式参考《动态表单事件扩展设计说明v1.0.docx》',
        response_data:'事件返回数据定义设定(执行正常情况下)，采用json格式，如果没有data返回则为空，格式参考《动态表单事件扩展设计说明v1.0.docx》'
    }]
    }")]
        public new object get()
        {
            SetCacheEnable(false);
            var up = DB.NewMetaUnitParameter();
            var list = (from t in DB.LamdaTable(up, "EXTEND_EVENTS4DFORM", "a")
                        select new
                        {
                            no = t.EventNo,
                            name = t.EventName,
                            category = t.EventCategory,
                            desc = t.EventDesc,
                            request_parameters = t.EventParameters,
                            response_data = t.EventReponseData
                        }).GetQueryList(up);
            return new
            {
                code = "success",
                msg = "",
                data = list
            };
        }
        [EWRARouteDesc("新增事件定义")]
        [EWRAAddInput("data", "array", @"待新增的数据列表，格式:
    [
    {
        no:'事件编号',
        name:'事件名称',
        category:'事件分类，如下：MetaData-元数据事件，Customerize-自定义',
        desc:'事件描述',
        request_parameters:'事件参数设定，采用json格式，格式参考《动态表单事件扩展设计说明v1.0.docx》',
        response_data:'事件返回数据定义设定(执行正常情况下)，采用json格式，如果没有data返回则为空，格式参考《动态表单事件扩展设计说明v1.0.docx》'
    }
    ]
    ", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
        [EWRAOutputDesc("返回结果", @"{
    code:'success-成功，failed-失败',
    msg:'提示信息'
    }")]
        public override object post()
        {
            var data = PostDataD.data;

            if (!(data is IEnumerable<object>))
                return new
                {
                    code = "failed",
                    msg = "参数格式不正确",
                };
            var datalist = (IEnumerable<object>)data;
            foreach (dynamic item in datalist)
            {
                if (ComFunc.nvl(item.no) == "")
                    return new
                    {
                        code = "failed",
                        msg = "编号不可为空"
                    };
                if (ComFunc.nvl(item.name) == "")
                    return new
                    {
                        code = "failed",
                        msg = "名称不可为空"
                    };
                if (ComFunc.nvl(item.request_parameters) != "")
                {
                    var dobj = FrameDLRObject.IsJsonThen(ComFunc.nvl(item.request_parameters), null, FrameDLRFlags.SensitiveCase);
                    if (dobj == null)
                        return new
                        {
                            code = "failed",
                            msg = "参数设定格式不正确"
                        };
                    else
                    {
                        if (ComFunc.nvl(dobj.RequestUrl) == "")
                        {
                            return new
                            {
                                code = "failed",
                                msg = "参数设定缺少请求URL"
                            };
                        }
                        if (ComFunc.nvl(dobj.RequestMethod) == "")
                        {
                            return new
                            {
                                code = "failed",
                                msg = "参数设定缺少请求Method"
                            };
                        }
                    }
                }
                if (ComFunc.nvl(item.response_data) != "")
                {
                    var dobj = FrameDLRObject.IsJsonThen(ComFunc.nvl(item.response_data), null, FrameDLRFlags.SensitiveCase);
                    if (dobj == null)
                        return new
                        {
                            code = "failed",
                            msg = "事件返回数据定义设定格式不正确"
                        };
                }
            }
            BeginTrans();
            var up = DB.NewMetaUnitParameter();
            var exists_list = (from t in DB.LamdaTable(up, "EXTEND_EVENTS4DFORM", "a")
                               select new { t.EventNo }).GetQueryList(up);
            var exists_nos = exists_list.Select(d => ComFunc.nvl(d.GetValue("EventNo"))).ToArray();
            foreach (dynamic item in datalist)
            {
                if (exists_nos.Contains((string)item.no))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"{item.no}该编号的事件已存在"
                    };
                }
            }

            foreach (dynamic item in datalist)
            {
                item.add_id = TokenPayLoad.ID;
                item.add_ip = ClientInfo.IP;
                item.add_name = ComFunc.nvl(TokenPayLoad["username"]);
                item.add_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                item.last_id = TokenPayLoad.ID;
                item.last_ip = ClientInfo.IP;
                item.last_name = ComFunc.nvl(TokenPayLoad["username"]);
                item.last_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

                DB.QuickInsert(up, "EXTEND_EVENTS4DFORM", new
                {
                    EventNo = item.no,
                    EventName = item.name,
                    EventCategory = item.category,
                    EventDesc = item.desc,
                    EventParameters = item.request_parameters,
                    EventReponseData = item.response_data,
                    add_id = TokenPayLoad.ID,
                    add_ip = ClientInfo.IP,
                    add_name = ComFunc.nvl(TokenPayLoad["username"]),
                    add_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                    last_id = TokenPayLoad.ID,
                    last_ip = ClientInfo.IP,
                    last_name = ComFunc.nvl(TokenPayLoad["username"]),
                    last_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                });
            }

            CommitTrans();
            return new
            {
                code = "success",
                msg = "操作成功"
            };
        }
        [EWRARouteDesc("修改资料")]
        [EWRARoute("patch", "/events4dform")]
        [EWRAAddInput("data", "array", @"待新增的数据列表，格式:
    [
    {
         no:'事件编号',
        name:'事件名称',
        category:'事件分类，如下：MetaData-元数据事件，Customerize-自定义',
        desc:'事件描述',
        request_parameters:'事件参数设定，采用json格式，格式参考《动态表单事件扩展设计说明v1.0.docx》',
        response_data:'事件返回数据定义设定(执行正常情况下)，采用json格式，如果没有data返回则为空，格式参考《动态表单事件扩展设计说明v1.0.docx》'
    }
    ]
    ", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
        [EWRAOutputDesc("返回结果", @"{
    code:'success-成功，failed-失败',
    msg:'提示信息'
    }")]
        public object Update()
        {
            var data = PostDataD.data;

            if (!(data is IEnumerable<object>))
                return new
                {
                    code = "failed",
                    msg = "参数格式不正确",
                };
            var datalist = (IEnumerable<object>)data;
            var nos = "";
            foreach (dynamic item in datalist)
            {
                if (ComFunc.nvl(item.no) == "")
                    return new
                    {
                        code = "failed",
                        msg = "编号不可为空"
                    };
                if (ComFunc.nvl(item.name) == "")
                    return new
                    {
                        code = "failed",
                        msg = "名称不可为空"
                    };
                if (ComFunc.nvl(item.request_parameters) != "")
                {
                    var dobj = FrameDLRObject.IsJsonThen(ComFunc.nvl(item.request_parameters), null, FrameDLRFlags.SensitiveCase);
                    if (dobj == null)
                        return new
                        {
                            code = "failed",
                            msg = "参数设定格式不正确"
                        };
                    else
                    {
                        if (ComFunc.nvl(dobj.RequestUrl) == "")
                        {
                            return new
                            {
                                code = "failed",
                                msg = "参数设定缺少请求URL"
                            };
                        }
                        if (ComFunc.nvl(dobj.RequestMethod) == "")
                        {
                            return new
                            {
                                code = "failed",
                                msg = "参数设定缺少请求Method"
                            };
                        }
                    }
                }
                if (ComFunc.nvl(item.response_data) != "")
                {
                    var dobj = FrameDLRObject.IsJsonThen(ComFunc.nvl(item.response_data), null, FrameDLRFlags.SensitiveCase);
                    if (dobj == null)
                        return new
                        {
                            code = "failed",
                            msg = "事件返回数据定义设定格式不正确"
                        };
                }
                nos += item.no + ",";
            }
            BeginTrans();
            var up = DB.NewMetaUnitParameter();
            var exists_list = (from t in DB.LamdaTable(up, "EXTEND_EVENTS4DFORM", "a")
                               where t.EventCategory == "Customerize" && t.EventNo.without(nos)
                               select new { t.EventNo }).GetQueryList(up);
            var exists_nos = exists_list.Select(d => ComFunc.nvl(d.GetValue("EventNo"))).ToArray();
            foreach (dynamic item in datalist)
            {
                if (exists_nos.Contains((string)item.no))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"{item.no}该编号的事件已存在"
                    };
                }
            }

            foreach (dynamic item in datalist)
            {
                item.add_id = TokenPayLoad.ID;
                item.add_ip = ClientInfo.IP;
                item.add_name = ComFunc.nvl(TokenPayLoad["username"]);
                item.add_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                item.last_id = TokenPayLoad.ID;
                item.last_ip = ClientInfo.IP;
                item.last_name = ComFunc.nvl(TokenPayLoad["username"]);
                item.last_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

                DB.QuickUpdate(up, "EXTEND_EVENTS4DFORM", new
                {
                    EventName = item.name,
                    EventCategory = item.category,
                    EventDesc = item.desc,
                    EventParameters = item.request_parameters,
                    EventReponseData = item.response_data,
                    last_id = TokenPayLoad.ID,
                    last_ip = ClientInfo.IP,
                    last_name = ComFunc.nvl(TokenPayLoad["username"]),
                    last_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                }, new
                {
                    EventNo = item.no
                });
            }

            CommitTrans();
            return new
            {
                code = "success",
                msg = "操作成功"
            };
        }
        [EWRARouteDesc("删除资料")]
        public override bool delete(string id)
        {
            var up = DB.NewMetaUnitParameter();
            BeginTrans();
            var exists_list = (from t in DB.LamdaTable(up, "EXTEND_EVENTS4DFORM", "a")
                               where t.EventNo == id
                               select t).GetQueryList(up);
            DB.QuickDelete(up, "EXTEND_EVENTS4DFORM", new
            {
                EventNo = id
            });
            CommitTrans();
            return true;
        }
        [EWRARoute("get", "/events4dform/alllist")]
        [EWRARouteDesc("获取所有的动态表单事件信息列表")]
        [EWRAOutputDesc("返回结果", @"{
    code:'success-成功，failed-失败',
    msg:'提示信息',
    data:[{
        no:'事件编号',
        name:'事件名称',
        category:'事件分类，如下：MetaData-元数据事件，Customerize-自定义',
        desc:'事件描述',
        request_parameters:'事件参数设定，采用json格式，格式参考《动态表单事件扩展设计说明v1.0.docx》',
        response_data:'事件返回数据定义设定(执行正常情况下)，采用json格式，如果没有data返回则为空，格式参考《动态表单事件扩展设计说明v1.0.docx》'
    }]
    }")]
        public object GetEvents4DF()
        {
            SetCacheEnable(false);
            var up = DB.NewMetaUnitParameter();
            var list = (from t in DB.LamdaTable(up, "EXTEND_EVENTS4DFORM", "a")
                        select new
                        {
                            no = t.EventNo,
                            name = t.EventName,
                            category = t.EventCategory,
                            desc = t.EventDesc,
                            request_parameters = t.EventParameters,
                            response_data = t.EventReponseData
                        }).GetQueryList(up);
            return new
            {
                code = "success",
                msg = "",
                data = list
            };
        }
        [EWRARoute("get", "/events4dform/{no}")]
        [EWRARouteDesc("获取指定动态表单事件信息")]
        [EWRAOutputDesc("返回结果", @"{
    code:'success-成功，failed-失败',
    msg:'提示信息',
    data:{
        no:'事件编号',
        name:'事件名称',
        category:'事件分类，如下：MetaData-元数据事件，Customerize-自定义',
        desc:'事件描述',
        request_parameters:'事件参数设定，采用json格式，格式参考《动态表单事件扩展设计说明v1.0.docx》',
        response_data:'事件返回数据定义设定(执行正常情况下)，采用json格式，如果没有data返回则为空，格式参考《动态表单事件扩展设计说明v1.0.docx》'
    }
    }")]
        public object GetEvent(string no)
        {
            SetCacheEnable(false);
            var up = DB.NewMetaUnitParameter();
            var list = (from t in DB.LamdaTable(up, "EXTEND_EVENTS4DFORM", "a")
                        where t.EventNo == no
                        select new
                        {
                            no = t.EventNo,
                            name = t.EventName,
                            category = t.EventCategory,
                            desc = t.EventDesc,
                            request_parameters = t.EventParameters,
                            response_data = t.EventReponseData
                        }).GetQueryList(up);
            if (list.Count <= 0)
            {
                return new
                {
                    code = "success",
                    msg = "无此事件信息"
                };
            }
            return new
            {
                code = "success",
                msg = "",
                data = list.First()
            };
        }
        [EWRARoute("patch", "/events4dform/script/export")]
        [EWRARouteDesc("导出动态表单事件的脚本")]
        [EWRAAddInput("nos", "string", "选中要导出的no，多个用逗号分隔", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
        [EWRAOutputDesc("返回结果", @"{
    code:'success-成功，failed-失败',
    msg:'提示信息',
    filetype:'文件类型',
    filename:'文件名称',
    filelength:'文件长度',
    file:'文件内容，采用base64加密'
    }")]
        object ExportScript()
        {
            string nos = ComFunc.nvl(PostDataD.nos);
            if (nos == "") return new
            {
                code = "failed",
                msg = "请选择要导出的表单事件"
            };
            var metaup = DB.NewMetaUnitParameter();
            var list = (from t in DB.LamdaTable(metaup, "EXTEND_EVENTS4DFORM", "a")
                        where t.EventNo.within(nos)
                        select t).GetQueryList(metaup);
            foreach (dynamic item in list)
            {
                item.add_time = DateTimeStd.IsDateTimeThen(item.add_time, "yyyy-MM-dd HH:mm:ss");
                item.last_time = DateTimeStd.IsDateTimeThen(item.last_time, "yyyy-MM-dd HH:mm:ss");
            }

            var dobj = FrameDLRObject.CreateInstance(FrameDLRFlags.SensitiveCase);
            dobj.EventList = list;
            var sign_str = ComFunc.getMD5_String(((FrameDLRObject)dobj).ToJSONString(true));
            dobj.ValidSign = sign_str;

            return FileHelper.DoDownLoad("dynamic_form_evnet.json", Encoding.UTF8.GetBytes(((FrameDLRObject)dobj).ToJSONString(true)));
        }
        [EWRARoute("patch", "/events4dform/script/import")]
        [EWRAEmptyValid("data")]
        [EWRARouteDesc("导入动态表单事件的脚本")]
        [EWRAAddInput("data", "json", @"导入的文件，格式如下：{
    filetype:'文件类型',
    filename:'文件名称',
    filelength:'文件长度',
    file:'文件内容，采用base64加密'
    }", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
        [EWRAOutputDesc("返回结果", @"{
    code:'success-成功，failed-失败',
    msg:'提示信息'
    }")]
        object ImportScript()
        {
            dynamic data = FrameDLRObject.IsJsonThen(PostDataD.data);
            var file = ComFunc.nvl(data.file);
            if (string.IsNullOrEmpty(file)) return new
            {
                code = "failed",
                msg = "上传文件无效，终止操作"
            };
            var content = ComFunc.IsBase64Then(file);
            if (content == "") return new
            {
                code = "failed",
                msg = "上传文件格式无效，终止操作"
            };
            var scripts = FrameDLRObject.IsJsonThen(content, null, EFFC.Frame.Net.Base.Constants.FrameDLRFlags.SensitiveCase);
            if (scripts == null) return new
            {
                code = "failed",
                msg = "上传文件格式无效，终止操作"
            };
            var valid_sign = ComFunc.nvl(scripts.GetValue("ValidSign"));
            if (valid_sign == null) return new
            {
                code = "failed",
                msg = "上传文件不合法，终止操作"
            };
            ((FrameDLRObject)scripts).Remove("ValidSign");
            var sign_str = ComFunc.getMD5_String(scripts.ToJSONString(true));
            if (sign_str != valid_sign) return new
            {
                code = "failed",
                msg = "上传文件校验失败，终止操作"
            };
            var eventlist = (IEnumerable<object>)scripts.GetValue("EventList");
            BeginTrans();
            var metaup = DB.NewMetaUnitParameter();
            foreach (dynamic s in eventlist)
            {
                DB.QuickDelete(metaup, "EXTEND_EVENTS4DFORM", new
                {
                    s.EventNo
                });
                DB.QuickInsert(metaup, "EXTEND_EVENTS4DFORM", s);
            }
            CommitTrans();
            return new
            {
                code = "success",
                msg = "操作成功"
            };
        }

        [EWRARoute("post", "/events4dform/{no}/eval")]
        [EWRARouteDesc("事件触发")]
        [EWRAAddInput("no", "string", "事件编号", "无默认值", RestInputPosition.Path, false)]
        [EWRAAddInput("this_data", "string", @"页面上当前编辑的行资料，先采用url编码，再采用base64编码，原数据格式:
    {
        column_name1:'值',
        column_name2:'值',
        .....
        column_nameN:'值',
    }", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
        [EWRAAddInput("parameters", "json对象", @"参数集合(包含querystring，post，path参数)，据格式:
    {
        key1:'值',
        key2:'值',
        .....
        key3:'值',
    }", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
        [EWRAOutputDesc("返回结果", @"{
    code:'success-成功，failed-失败',
    msg:'提示信息'
    }")]
        object CallEvent(string no)
        {
            var data_str = ComFunc.nvl(PostDataD.this_data).Replace(" ", "+");
            var this_data_base64str = ComFunc.IsBase64Then(data_str);
            string this_data_str = ComFunc.UrlDecode(this_data_base64str);
            var this_data = FrameDLRObject.IsJsonThen(this_data_str);
            var parameters = PostDataD.parameters;
            var up = DB.NewMetaUnitParameter();

            return DoCallEvent(up, no, this_data, parameters);
        }
        /// <summary>
        /// 执行事件
        /// </summary>
        /// <param name="up"></param>
        /// <param name="id"></param>
        /// <param name="this_data"></param>
        /// <returns></returns>
        private object DoCallEvent(UnitParameter up, string id, object this_data, object param_values)
        {
            var list = (from t in DB.LamdaTable(up, "EXTEND_EVENTS4DFORM", "a")
                        where t.EventNo == id
                        select new
                        {
                            no = t.EventNo,
                            name = t.EventName,
                            category = t.EventCategory,
                            desc = t.EventDesc,
                            parameters = t.EventParameters
                        }).GetQueryList(up);
            if (list.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "执行失败：事件设定不存在"
                };
            }
            dynamic info = list.First();
            var event_call = new EventsCall();
            var parameters = FrameDLRObject.IsJsonThen(info.parameters, null, FrameDLRFlags.SensitiveCase);
            if (parameters == null)
            {
                return new
                {
                    code = "failed",
                    msg = "执行失败：确少执行参数"
                };
            }
            string url = ComFunc.nvl(parameters.RequestUrl);
            string method = ComFunc.nvl(parameters.RequestMethod);
            FrameDLRObject path_data = ComFunc.nvl(parameters.RequestPath) == "" ? null : parameters.RequestPath;
            FrameDLRObject query_string = ComFunc.nvl(parameters.RequestQueryString) == "" ? null : parameters.RequestQueryString;
            FrameDLRObject header = ComFunc.nvl(parameters.RequestHeader) == "" ? null : parameters.RequestHeader;
            FrameDLRObject post_data = ComFunc.nvl(parameters.RequestPostData) == "" ? null : parameters.RequestPostData;
            var call_context = new EventsCall.EventsCallContext();
            call_context.RowData = this_data;
            call_context.Login_ID = TokenPayLoad.ID;
            call_context.Login_Name = ComFunc.nvl(TokenPayLoad["username"]);
            call_context.SetParameterValues(param_values);

            event_call.FixData(path_data, call_context);
            event_call.FixData(query_string, call_context);
            event_call.FixData(header, call_context);
            event_call.FixData(post_data, call_context);
            url = event_call.FixUrl(url, path_data);
            if (url.StartsWith("~"))
            {
                return CallLocalLogic(url.Replace("~", ""), method, header, query_string, post_data, false);
            }
            else
            {
                if (query_string != null)
                {
                    var qs = "";
                    foreach (var item in query_string.Items)
                    {
                        qs += $"{item.Key}={ComFunc.UrlEncode(item.Value)}&";
                    }
                    qs = qs.Length > 0 ? qs.Substring(0, qs.Length - 1) : "";
                    if (url.IndexOf("?") > 0)
                    {

                        url += $"&{qs}";
                    }
                    else
                    {
                        url += $"?{qs}";
                    }
                }
                string result = event_call.Send(url, method, call_context, header, post_data);
                if (result == null)
                {
                    return new
                    {
                        code = "failed",
                        msg = "执行失败：返回结果为空"
                    };
                }
                else if (result.StartsWith("Failed:"))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"执行失败：{result}"
                    };
                }
                else
                {
                    return FrameDLRObject.IsJsonThen(result, null, FrameDLRFlags.SensitiveCase);
                }
            }
        }
    }
}
